//
// Created by Woory Dont on 2023/11/4.
//
#include <gtest/gtest.h>
#include <algorithm>
#include <random>
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <iterator>
#include <map>
#include <unordered_map>

using std::cout;
using std::endl;
using namespace std;
TEST(std, s1)
{
  std::cout << "hw" << std::endl;
}

TEST(lam, l1)
{
  const double x = []
  {
	double tmp = 3;
	for (int i = 0; i < 3; i++)
	  {
		tmp++;
	  }
	return tmp;
  } ();
  cout << x << endl;
}

struct OpObj {
  int x = 1;
  std::string name = "asd";
};

TEST(OPtion, o1)
{
  std::optional<OpObj> opObj = OpObj ();

  cout << opObj.value ().x << endl;
  cout << opObj.value ().name << endl;
  std::optional<OpObj> opObj1;
  cout << opObj1.has_value () << endl;
}

struct TObject {
  string id;
  int count;
};

TObject *Change (TObject *tObject, vector<TObject> &tss)
{
  if (tObject->id == "CM97")
	{
	  return &tss[1];
	}
  return tObject;
}

TEST(Ref, r1)
{
  vector<TObject> ts = {{"CM97", 780},
						{"iWwDyc9", 618},
						{"eXGFVo0", 892}};

  for (auto &t : ts)
	{
	  cout << t.id << " " << t.count << endl;
	}
  auto item1 = find_if (ts.begin (), ts.end (),
						[] (const TObject &t)
						{
						  return t.id == "CM97";
						});
//    auto item2 = ranges::find_if(ts, [](const TObject &t) { return t.id == "iWwDyc9"; });
  for (auto &item : ts)
	{
	  TObject *t_ref = &item;
	  t_ref = Change (t_ref, ts);
	  t_ref->count++;
	}
  cout << "after---------" << endl;
  for (auto &t : ts)
	{
	  cout << t.id << " " << t.count << endl;
	}

}

TEST(Ref, r2)
{
  vector<TObject> ts = {{"CM97", 780},
						{"iWwDyc9", 618},
						{"eXGFVo0", 892}};

  for (auto &t : ts)
	{
	  cout << t.id << " " << t.count << endl;
	}
  for (auto item : ts)
	{
	  item.count = 1000;
	}
  cout << "111111after---------" << endl;
  for (auto &t : ts)
	{
	  cout << t.id << " " << t.count << endl;
	}

  for (auto item : ts)
	{
	  TObject *t_ptr = &item;
	  t_ptr->count = 681;
	}

  cout << "22222222 after---------" << endl;
  for (auto &t : ts)
	{
	  cout << t.id << " " << t.count << endl;
	}
  for (auto &item : ts)
	{
	  item.count++;
	}
  cout << "r2--------after---------" << endl;
  for (auto &t : ts)
	{
	  cout << t.id << " " << t.count << endl;
	}

}

TEST(pref, p1)
{
  int ii = 490;
  int &i_ref = ii;
  int *i_ptr = &i_ref;
  cout << "i_ref = " << i_ref << endl;
  (*i_ptr) = 911;
  cout << "i_ref = " << i_ref << endl;
  cout << "ii = " << ii << endl;
}

TEST(parallel, for1)
{
#pragma omp parallel for
  for (int i = 0; i < 10; i++)
	{
	  cout << i << endl;
	}
}

class Base {
 public:
  Base ()
  {
	std::cout << "Base class constructor" << std::endl;
  }
  ~Base ()
  {
	std::cout << "Base class destructor" << std::endl;
  }
};

class Derived : public Base {
 public:
  Derived ()
  {
	std::cout << "Derived class constructor" << std::endl;
  }
  ~Derived ()
  {
	std::cout << "Derived class destructor" << std::endl;
  }
};

TEST(std_construct, sc1)
{
  {
	Derived derivedObj;
  }
}

TEST(vector, insert1)
{
  vector<int> vec_int = {106, 554, 593, 613, 928};
  vector<int> vec_int1;
  int i = 4;
  int j = 5;
  vec_int1.insert (vec_int1.end (), vec_int.begin () + i, vec_int.begin () + j);
  for (auto item : vec_int1)
	{
	  cout << item << ",";
	}
};

TEST(random, r1)
{
  std::random_device rd;
  std::mt19937 gen (rd ());
  std::uniform_int_distribution dist (1, 10);
  for (int i = 0; i < 10; ++i)
	{
	  cout << dist (gen) << endl;
	}
}

TEST(vector, insert2)
{
  vector<int> vecs;
  vecs.insert (vecs.begin () + 0, 11);
  for (auto v : vecs)
	{
	  cout << v << endl;
	}
};

TEST(sizeT, s1)
{
  vector<int> ss;
  for (int i = 0; i < static_cast<int> (ss.size ()) - 1; i++)
	{
	  cout << ss[i];
	}
  cout << "done";
};

TEST(sizeT, s2)
{
  vector<int> ss;
  int size = ss.size ();

  for (auto it = ss.begin (); it != ss.end () - 1; it++)
	{
	  cout << *it;
	}
  cout << "done";
};

struct MyStruct {
  int someValue;
  bool isTrue;

  // 构造函数
  MyStruct (int value, bool flag) : someValue (value), isTrue (flag)
  {}
};

TEST(sort, s1)
{
  std::vector<MyStruct> myVector = {
	  {1, true},
	  {2, false},
	  {3, true},
	  {4, false},
	  {5, true}
  };

  // 使用 lambda 表达式进行排序
  std::sort (myVector.begin (), myVector.end (), [] (const MyStruct &a, const MyStruct &b)
  {
	return a.isTrue;
  });

  // 输出排序结果
  for (const auto &element : myVector)
	{
	  std::cout << "Value: " << element.someValue << ", isTrue: " << element.isTrue << std::endl;
	}

}

TEST(trycatch, t1)
{
  try
	{
	  int numerator, denominator;
	  std::cout << "Enter numerator: ";
	  std::cin >> numerator;
	  std::cout << "Enter denominator: ";
	  std::cin >> denominator;

	  if (denominator == 0)
		{
		  throw std::runtime_error ("Denominator cannot be zero.");
		}

	  int result = numerator / denominator;
	  std::cout << "Result: " << result << std::endl;
	}
  catch (std::exception &e)
	{
	  std::cerr << "Exception caught: " << e.what () << std::endl;
	}
  catch (...)
	{
	  std::cerr << "Unknown exception caught." << std::endl;
	}

}

TEST(stdvector, sv1)
{
  std::vector<int> vs = {1, 3, 4, 5, 6, 7, 9};
  for (int i = 0; i < vs.size (); i++)
	{
	  if (i == 5)
		{
		  vs[i] = 11;
		}
	}
  for (auto v : vs)
	{
	  std::cout << v << std::endl;
	}
}

std::vector<int> selectRandomElements (const std::vector<int> &source, size_t count)
{
  if (count > source.size ())
	{
	  throw std::invalid_argument ("Count cannot be greater than the size of the source vector.");
	}

  std::vector<int> selectedElements;
  selectedElements.reserve (count);

  // 使用Mersenne Twister随机数生成器  
  std::random_device rd;
  std::mt19937 g (rd ());

  // 创建一个均匀分布的随机数生成器，范围从0到source.size() - 1  
  std::uniform_int_distribution<> dis (0, source.size () - 1);

  while (selectedElements.size () < count)
	{
	  int randomIndex = dis (g);
	  // 检查是否已经选择了该元素  
	  if (std::find (selectedElements.begin (), selectedElements.end (), source[randomIndex])
		  == selectedElements.end ())
		{
		  selectedElements.push_back (source[randomIndex]);
		}
	}

  return selectedElements;
}

TEST(stdvector, r1)
{
  std::vector<int> source = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  size_t count = 5; // 要选择的元素数量  

  try
	{
	  std::vector<int> selected = selectRandomElements (source, count);
	  std::cout << "Selected elements: ";
	  for (int num : selected)
		{
		  std::cout << num << " ";
		}
	  std::cout << std::endl;
	}
  catch (const std::exception &e)
	{
	  std::cerr << "Error: " << e.what () << std::endl;
	}

}

TEST(stdvector, find1)
{
  std::shared_ptr<int> s_p;
  {
	int x = 5;
	std::cout << x << std::endl;
	s_p = std::make_shared<int> (x);
  }
  std::cout << "after:" << X_OK << endl;
  std::cout << "after:" << *s_p << endl;
}
void logerr (const std::string &filename, const int line, const std::string &msg)
{
  std::cout << msg << std::endl;
  std::cout << filename << ":" << line << endl;
}
#define GRR(x) logerr(__FILE__,__LINE__,x);
#define LOG(message) std::cout << __FILE__ << ":" << __LINE__ <<"\n" << message << std::endl;
TEST (honghai, h1)
{
  char *msg = "asd";
  char *f1 = "pre1";
  char *f2 = "pre2";
//  logerr (__FILE__,__LINE__,msg);

  GRR(msg);
//  logerr (__FILE__,__LINE__,msg);
//  LOG(msg);
}

TEST(sort, s2)
{

  std::vector<int> vec = {4, 2, 9, 6, 5, 1, 8, 3, 7};
  std::vector<size_t> indices (vec.size ());

  // 初始化索引数组  
  for (size_t i = 0; i < vec.size (); ++i)
	{
	  indices[i] = i;
	}

  // 使用自定义比较函数进行排序，该函数使用原始向量中的值但排序索引  
  std::sort (indices.begin (), indices.end (),
			 [&vec] (size_t a, size_t b)
			 {
			   return vec[a] < vec[b];
			 }
  );

  // 输出排序后的索引和对应的值  
  for (size_t i = 0; i < indices.size (); ++i)
	{
	  std::cout << "Index " << indices[i] << " has value " << vec[indices[i]] << std::endl;
	}
// 输出排序后的索引和对应的值  
  for (size_t i = 0; i < vec.size (); ++i)
	{
	  std::cout << "Index " << vec[i];
	}
}
TEST(vector, v1)
{
  std::vector<std::shared_ptr<MyStruct>> mss;
  std::unordered_map<int, std::shared_ptr<MyStruct>> mymap;
  std::unordered_map<int, MyStruct *> myprtmap;
  mss.reserve (10000);
  for (int i = 0; i < 10000; ++i)
	{
	  MyStruct my_struct (i, false);
	  auto ss = std::make_shared<MyStruct> (my_struct);
	  mss.push_back (ss);
//	  mss.push_back(std::make_shared<MyStruct>(my_struct));

	  mymap.insert ({i, ss});
	  myprtmap.insert ({i, &my_struct});
//	  mymap.insert({i,std::make_shared<MyStruct>(my_struct)});
	}

  for (int i = 0; i < 100; ++i)
	{
	  mss[i]->someValue = i - 100;
	}

  for (int i = 0; i < 100; ++i)
	{
	  std::cout << mss[i]->someValue << "," << mymap.at (i)->someValue << "," << myprtmap.at (i)->someValue << endl;
	}
}

TEST(vector, ir1)
{
  std::vector<int> vec1 = {1, 2, 3, 4};
  std::vector<int> vec2 = {5, 6, 7, 8};
  vec1.insert (vec1.end (), vec2.rbegin (), vec2.rend ());
  for (int i = 0; i < vec1.size (); ++i)
	{
	  cout << vec1[i] << endl;
	}
}

TEST(vector, min_max)
{
  std::vector<double> ds;
  ds.push_back (1231.1);
  ds.push_back (231.1);
  auto ptr = std::min_element (ds.begin (), ds.end ());
  auto ptr2 = std::max_element (ds.begin (), ds.end ());
  if (ptr != ds.end ())
	{
	  cout << *ptr << endl;
	}

  if (ptr2 != ds.end ())
	{
	  cout << *ptr2 << endl;
	}
}

TEST(vector, chuyu)
{
  std::vector<int> ins = {-360, 0, 360};
  for (int i = 0; i < ins.size (); ++i)
	{
	  cout << ins[i] % 360 << endl;
	}
}

TEST(vector, remove_if)
{
  std::vector<int> vec = {4, 2, 9, 6, 5, 1, 8, 3, 7};
  std::vector<int>::iterator it;
  it = std::remove_if (vec.begin (), vec.end (), [] (int i)
  { return i % 2 == 0; });
  vec.erase (it, vec.end ());
  for (int i = 0; i < vec.size (); ++i)
	{
	  cout << vec[i] << endl;
	}
}

#include <unordered_set>

TEST(uset, s1)
{
  std::unordered_set<int> mySet;
  mySet.insert (1);
  mySet.insert (2);
  mySet.insert (3);
  size_t count = mySet.count (2); // 判断元素 2 是否存在
  if (count > 0)
	{
	  // 元素存在
	  cout << "存在" << endl;
	}
  else
	{
	  // 元素不存在
	  cout << "不存在" << endl;
	}
  for (auto i : mySet)
	{
	  cout << i << endl;
	}
  mySet.insert (1);
  for (auto i : mySet)
	{
	  cout << i << endl;
	}
}